import pymysql
from collections import defaultdict
import datetime


# using dict store and statistics the port probability
# asuming that port is an independent attribute whth each other

def prior_probablity():
    connection = pymysql.connect(host='localhost',
                                 user='root',
                                 password='123456',
                                 db='aisdb_suntao',
                                 charset='utf8mb4',
                                 cursorclass=pymysql.cursors.DictCursor)
    # there are 3 types of ships, using 1 for bulk_carries, 2 for container, 3 for oil_tanker
    try:
        with connection.cursor() as cursor:
            cursor.execute("select mmsi, ship_type from train_mmsi")
            shiplist = cursor.fetchall()

            # init dict for store prior probality
            port_probality1 = defaultdict(int)
            port_probality2 = defaultdict(int)
            port_probality3 = defaultdict(int)

            port_probality = [port_probality1, port_probality2, port_probality3]

            # init dict for store target number
            target_number = defaultdict(int)

            for ship in shiplist:
                mmsi = ship["mmsi"]
                ship_type = ship["ship_type"]

                cursor.execute("SELECT World_port_index_number_src, World_port_index_number_dst "
                               "FROM l2_port_port_journey_15 where MMSI = %s", mmsi)
                portlist = cursor.fetchall()

                for port in portlist:
                    port_probality[ship_type - 1][port["World_port_index_number_src"]] += 1
                    port_probality[ship_type - 1][port["World_port_index_number_dst"]] += 1

                target_number[ship_type - 1] += 1

                print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"), target_number)
                print(port_probality)
                if sum(target_number.values()) > 200:
                    break
    finally:
        connection.close()

    return port_probality, target_number


def estimate(port_probality, target_number):
    connection = pymysql.connect(host='localhost',
                                 user='root',
                                 password='123456',
                                 db='aisdb_suntao',
                                 charset='utf8mb4',
                                 cursorclass=pymysql.cursors.DictCursor)

    try:
        with connection.cursor() as cursor:
            cursor.execute("select mmsi, ship_type from test_mmsi")
            shiplist = cursor.fetchall()

            total_count = 0
            correct_count = 0

            for ship in shiplist:
                mmsi = ship["mmsi"]
                ship_type = ship["ship_type"]

                cursor.execute("SELECT World_port_index_number_src, World_port_index_number_dst "
                               "FROM l2_port_port_journey_15 where MMSI = %s", mmsi)
                portlist = cursor.fetchall()

                portset = set()
                for port in portlist:
                    portset.add(port["World_port_index_number_src"])
                    portset.add(port["World_port_index_number_dst"])

                if len(portset) == 0:
                    continue

                if max_probability(portset, port_probality, target_number) == int(ship_type):
                    correct_count += 1
                total_count += 1

    finally:
        connection.close()
    print(correct_count, total_count, correct_count / total_count)


def max_probability(port_set, port_probality, target_number):
    port_set, port_probality, target_number = laplace_smoothing(port_set, port_probality, target_number)

    p1 = 1
    p2 = 1
    p3 = 1

    for port in port_set:
        p1 *= port_probality[0][port] / sum(port_probality[0].values())
        p2 *= port_probality[1][port] / sum(port_probality[1].values())
        p3 *= port_probality[2][port] / sum(port_probality[2].values())

    p1 *= target_number[0] / sum(target_number.values())
    p2 *= target_number[1] / sum(target_number.values())
    p3 *= target_number[2] / sum(target_number.values())

    print(p1, p2, p3)
    return [p1, p2, p3].index(max([p1, p2, p3])) + 1


def laplace_smoothing(portset, port_probality, target_number):
    for i in [0, 1, 2]:
        for port in portset:
            if port not in port_probality[i].keys():
                port_probality[i][port] = 0

    for i in [0, 1, 2]:
        for port in port_probality[i].keys():
            port_probality[i][port] += 1

        target_number[i] += 1

    return portset, port_probality, target_number


if __name__ == "__main__":
    port_probality, target_number = prior_probablity()
    estimate(port_probality, target_number)
